// @Author EthanScriptOn
// @Desc
package identity

import (
	"sync"
	"time"
)

// IdentityInformationCarrier Identity wrappers allow identity information to be generated and stored in concurrent environments,
// which is suitable for scenarios where identity information is fixed
type IdentityInformationCarrier struct {
	strategy IdentityInformation
	identity interface{}
	mu       *sync.RWMutex
}

func GenerateIdentityInformationCarrierWithStrategy(strategy IdentityInformation) *IdentityInformationCarrier {
	return &IdentityInformationCarrier{strategy: strategy, mu: &sync.RWMutex{}}
}

func GenerateIdentityInformationCarrierWithIdentity(identity interface{}) *IdentityInformationCarrier {
	return &IdentityInformationCarrier{identity: identity}
}

// GenerateUniqueIdentifier Generate an identity, which is thread-safe, using double-check detection
func (i *IdentityInformationCarrier) GenerateUniqueIdentifier() (interface{}, error) {
retry:
	if i.identity != nil {
		return i.identity, nil
	}
	if i.mu.TryLock() {
		defer i.mu.Unlock()
		if i.identity != nil {
			return i.identity, nil
		}
		identifier, err := i.strategy.GenerateUniqueIdentifier()
		i.identity = identifier
		return identifier, err
	}
	time.Sleep(time.Millisecond)
	goto retry
}
